#include "semant.h"
#include "../include/SysY_tree.h"
#include "../include/ir.h"
#include "../include/type.h"
/*
    语义分析阶段需要对语法树节点上的类型和常量等信息进行标注, 即NodeAttribute类
    同时还需要标注每个变量的作用域信息，即部分语法树节点中的scope变量
    你可以在utils/ast_out.cc的输出函数中找到你需要关注哪些语法树节点中的NodeAttribute类及其他变量
    以及对语义错误的代码输出报错信息
*/

/*
    错误检查的基本要求:
    • 检查 main 函数是否存在 (根据SysY定义，如果不存在main函数应当报错)；
    • 检查未声明变量，及在同一作用域下重复声明的变量；
    • 条件判断和运算表达式：int 和 bool 隐式类型转换（例如int a=5，return a+!a）；
    • 数值运算表达式：运算数类型是否正确 (如返回值为 void 的函数调用结果是否参与了其他表达式的计算)；
    • 检查未声明函数，及函数形参是否与实参类型及数目匹配；
    • 检查是否存在整型变量除以整型常量0的情况 (如对于表达式a/(5-4-1)，编译器应当给出警告或者直接报错)；

    错误检查的进阶要求:
    • 对数组维度进行相应的类型检查 (例如维度是否有浮点数，定义维度时是否为常量等)；
    • 对float进行隐式类型转换以及其他float相关的检查 (例如模运算中是否有浮点类型变量等)；
*/
extern LLVMIR llvmIR;

SemantTable semant_table;
std::vector<std::string> error_msgs{}; // 将语义错误信息保存到该变量中

static bool mainFound = false;

//这两个map用来存初始化的值val
std::map<std::string, VarAttribute> ConstGlobalMap;
std::map<std::string, VarAttribute> StaticGlobalMap;

//下面这些函数已知两个操作数的类型和运算符op，进行具体的运算
NodeAttribute binary_int_add(NodeAttribute a,NodeAttribute b){
    NodeAttribute result;
    result.T.type = Type::INT;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.IntVal = a.V.val.IntVal + b.V.val.IntVal;
    }
    return result;
}

NodeAttribute binary_int_sub(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::INT;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.IntVal = a.V.val.IntVal - b.V.val.IntVal;
    }
    return result;
}

NodeAttribute binary_int_mul(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::INT;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.IntVal = a.V.val.IntVal * b.V.val.IntVal;
    }
    return result;
}

NodeAttribute binary_int_div(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    if(b.V.ConstTag==1&&b.V.val.IntVal==0){
        result.T.type = Type::VOID;
        result.V.ConstTag = 0;
        //报错
        //error_msgs.push_back("div 0 in line " + std::to_string(b.line_number) + "\n");
        return result;
    }
    result.T.type = Type::INT;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.IntVal = a.V.val.IntVal / b.V.val.IntVal;
    }
    return result;
}

NodeAttribute binary_int_mod(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::INT;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.IntVal = a.V.val.IntVal % b.V.val.IntVal;
    }
    return result;
}

NodeAttribute binary_int_leq(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.IntVal <= b.V.val.IntVal;
    }
    return result;
}

NodeAttribute binary_int_lt(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.IntVal < b.V.val.IntVal;
    }
    return result;
}

NodeAttribute binary_int_geq(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.IntVal >= b.V.val.IntVal;
    }
    return result;
}

NodeAttribute binary_int_gt(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.IntVal > b.V.val.IntVal;
    }
    return result;
}

NodeAttribute binary_int_eq(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.IntVal == b.V.val.IntVal;
    }
    return result;
}

NodeAttribute binary_int_neq(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.IntVal != b.V.val.IntVal;
    }
    return result;
}

NodeAttribute binary_int_and(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.IntVal && b.V.val.IntVal;
    }
    return result;
}

NodeAttribute binary_int_or(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.IntVal || b.V.val.IntVal;
    }
    return result;
}

//这是float
NodeAttribute binary_float_add(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::FLOAT;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.FloatVal = a.V.val.FloatVal + b.V.val.FloatVal;
    }
    return result;
}

NodeAttribute binary_float_sub(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::FLOAT;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.FloatVal = a.V.val.FloatVal - b.V.val.FloatVal;
    }
    return result;
}

NodeAttribute binary_float_mul(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::FLOAT;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.FloatVal = a.V.val.FloatVal * b.V.val.FloatVal;
    }
    return result;
}

NodeAttribute binary_float_div(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    if(b.V.ConstTag==1&&b.V.val.FloatVal==0){
        result.T.type = Type::VOID;
        result.V.ConstTag = 0;
        //报错
        //error_msgs.push_back("div 0 in line " + std::to_string(b.line_number) + "\n");
        return result;
    }
    result.T.type = Type::FLOAT;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.FloatVal = a.V.val.FloatVal / b.V.val.FloatVal;
    }
    return result;
}

NodeAttribute binary_float_mod(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::VOID;
    result.V.ConstTag = 0;
    //报错
    //error_msgs.push_back("mod on float type in line " + std::to_string(a.line_number) + "\n");
    return result;
}

NodeAttribute binary_float_leq(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.FloatVal <= b.V.val.FloatVal;
    }
    return result;
}

NodeAttribute binary_float_lt(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.FloatVal < b.V.val.FloatVal;
    }
    return result;
}

NodeAttribute binary_float_geq(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.FloatVal >= b.V.val.FloatVal;
    }
    return result;
}

NodeAttribute binary_float_gt(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.FloatVal > b.V.val.FloatVal;
    }
    return result;
}

NodeAttribute binary_float_eq(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.FloatVal == b.V.val.FloatVal;
    }
    return result;
}

NodeAttribute binary_float_neq(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.FloatVal != b.V.val.FloatVal;
    }
    return result;
}

NodeAttribute binary_float_and(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.FloatVal && b.V.val.FloatVal;
    }
    return result;
}

NodeAttribute binary_float_or(NodeAttribute a, NodeAttribute b) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag & b.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = a.V.val.FloatVal || b.V.val.FloatVal;
    }
    return result;
}


//这个函数已知两个操作数的类型，根据不同的运算符op进行不同的运算
NodeAttribute binary_int_int(NodeAttribute a,NodeAttribute b,std::string op){
    if(op=="+"){
        return binary_int_add(a,b);
    }
    else if(op=="-"){
        return binary_int_sub(a,b);
    }
    else if(op=="*"){
        return binary_int_mul(a,b);
    }
    else if(op=="/"){
        return binary_int_div(a,b);
    }
    else if(op=="%"){
        return binary_int_mod(a,b);
    }
    else if(op=="<="){
        return binary_int_leq(a,b);
    }
    else if(op=="<"){
        return binary_int_lt(a,b);
    }
    else if(op==">="){
        return binary_int_geq(a,b);
    }
    else if(op==">"){
        return binary_int_gt(a,b);
    }
    else if(op=="=="){
        return binary_int_eq(a,b);
    }
    else if(op=="!="){
        return binary_int_neq(a,b);
    }
    else if(op=="&&"){
        return binary_int_and(a,b);
    }
    else if(op=="||"){
        return binary_int_or(a,b);
    }
}

NodeAttribute binary_float_float(NodeAttribute a,NodeAttribute b,std::string op){
    if(op=="+"){
        return binary_float_add(a,b);
    }
    else if(op=="-"){
        return binary_float_sub(a,b);
    }
    else if(op=="*"){
        return binary_float_mul(a,b);
    }
    else if(op=="/"){
        return binary_float_div(a,b);
    }
    else if(op=="%"){
        return binary_float_mod(a,b);
    }
    else if(op=="<="){
        return binary_float_leq(a,b);
    }
    else if(op=="<"){
        return binary_float_lt(a,b);
    }
    else if(op==">="){
        return binary_float_geq(a,b);
    }
    else if(op==">"){
        return binary_float_gt(a,b);
    }
    else if(op=="=="){
        return binary_float_eq(a,b);
    }
    else if(op=="!="){
        return binary_float_neq(a,b);
    }
    else if(op=="&&"){
        return binary_float_and(a,b);
    }
    else if(op=="||"){
        return binary_float_or(a,b);
    }
}
NodeAttribute binary_int_float(NodeAttribute a,NodeAttribute b,std::string op){
    //把int转成float
    NodeAttribute a_float = a;
    a_float.T.type = Type::FLOAT;
    a_float.V.val.FloatVal = (float)a.V.val.IntVal;
    return binary_float_float(a_float,b,op);
}

NodeAttribute binary_int_bool(NodeAttribute a,NodeAttribute b,std::string op){
    //把bool转成int
    NodeAttribute b_int = b;
    b_int.T.type = Type::INT;
    b_int.V.val.IntVal = b.V.val.BoolVal;
    return binary_int_int(a,b_int,op);
}

NodeAttribute binary_float_bool(NodeAttribute a,NodeAttribute b,std::string op){
    //把bool转成float
    NodeAttribute b_float = b;
    b_float.T.type = Type::FLOAT;
    b_float.V.val.FloatVal = b.V.val.BoolVal;
    return binary_float_float(a,b_float,op);
}

NodeAttribute binary_bool_bool(NodeAttribute a,NodeAttribute b,std::string op){
    //把bool转成int
    NodeAttribute a_int = a;
    NodeAttribute b_int = b;
    a_int.T.type = Type::INT;
    a_int.V.val.IntVal = a.V.val.BoolVal;
    b_int.T.type = Type::INT;
    b_int.V.val.IntVal = b.V.val.BoolVal;
    return binary_int_int(a_int,b_int,op);
}

NodeAttribute binary_error(NodeAttribute a,NodeAttribute b,std::string op){
    //error_msgs.push_back("operators is invaild in line " + std::to_string(a.line_number) + "\n");
    NodeAttribute result;
    result.T.type = Type::VOID;
    result.V.ConstTag = 0;
    return result;
}


//这个函数根据两个操作数的类型来处理
NodeAttribute cal_binary_attribute(NodeAttribute a,NodeAttribute b,std::string op){
    if(a.T.type==Type::INT&&b.T.type==Type::INT){
        return binary_int_int(a,b,op);
    }
    else if(a.T.type==Type::INT&&b.T.type==Type::FLOAT){
        return binary_int_float(a,b,op);
    }
    else if(a.T.type==Type::INT&&b.T.type==Type::BOOL){
        return binary_int_bool(a,b,op);
    }
    else if(a.T.type==Type::INT&&b.T.type==Type::PTR){
        return binary_error(a,b,op);
    }
    else if(a.T.type==Type::INT&&b.T.type==Type::VOID){
        return binary_error(a,b,op);
    }
    else if(a.T.type==Type::FLOAT&&b.T.type==Type::INT){
        return binary_int_float(b,a,op);
    }
    else if(a.T.type==Type::FLOAT&&b.T.type==Type::FLOAT){
        return binary_float_float(a,b,op);
    }
    else if(a.T.type==Type::FLOAT&&b.T.type==Type::BOOL){
        return binary_float_bool(a,b,op);
    }
    else if(a.T.type==Type::FLOAT&&b.T.type==Type::PTR){
        return binary_error(a,b,op);
    }
    else if(a.T.type==Type::FLOAT&&b.T.type==Type::VOID){
        return binary_error(a,b,op);
    }
    else if(a.T.type==Type::BOOL&&b.T.type==Type::INT){
        return binary_int_bool(b,a,op);
    }
    else if(a.T.type==Type::BOOL&&b.T.type==Type::FLOAT){
        return binary_float_bool(b,a,op);
    }
    else if(a.T.type==Type::BOOL&&b.T.type==Type::BOOL){
        return binary_bool_bool(a,b,op);
    }
    else if(a.T.type==Type::BOOL&&b.T.type==Type::PTR){
        return binary_error(a,b,op);
    }
    else if(a.T.type==Type::BOOL&&b.T.type==Type::VOID){
        return binary_error(a,b,op);
    }
    else if(a.T.type==Type::PTR){
        return binary_error(a,b,op);
    }
    else if(a.T.type==Type::VOID){
        return binary_error(a,b,op);
    }   
}






//下面是单目运算符
NodeAttribute single_int_add(NodeAttribute a){
    NodeAttribute result;
    result.T.type = Type::INT;
    result.V.ConstTag = a.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.IntVal = a.V.val.IntVal;
    }
    return result;
}

NodeAttribute single_int_sub(NodeAttribute a) {
    NodeAttribute result;
    result.T.type = Type::INT;
    result.V.ConstTag = a.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.IntVal = -a.V.val.IntVal;
    }
    return result;
}

NodeAttribute single_int_not(NodeAttribute a) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = !a.V.val.IntVal;
    }
    return result;
}

NodeAttribute single_float_add(NodeAttribute a) {
    NodeAttribute result;
    result.T.type = Type::FLOAT;
    result.V.ConstTag = a.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.FloatVal = a.V.val.FloatVal;
    }
    return result;
}

NodeAttribute single_float_sub(NodeAttribute a) {
    NodeAttribute result;
    result.T.type = Type::FLOAT;
    result.V.ConstTag = a.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.FloatVal = -a.V.val.FloatVal;
    }
    return result;
}

NodeAttribute single_float_not(NodeAttribute a) {
    NodeAttribute result;
    result.T.type = Type::BOOL;
    result.V.ConstTag = a.V.ConstTag;
    if (result.V.ConstTag) {
        result.V.val.BoolVal = !a.V.val.FloatVal;
    }
    return result;
}


NodeAttribute single_int(NodeAttribute a,std::string op){
    if(op=="+"){
        return single_int_add(a);
    }
    else if(op=="-"){
        return single_int_sub(a);
    }
    else if(op=="!"){
        return single_int_not(a);
    }
}

NodeAttribute single_float(NodeAttribute a,std::string op){
    if(op=="+"){
        return single_float_add(a);
    }
    else if(op=="-"){
        return single_float_sub(a);
    }
    else if(op=="!"){
        return single_float_not(a);
    }
}

NodeAttribute single_bool(NodeAttribute a, std::string op) {
    NodeAttribute a_int = a;
    a_int.T.type = Type::INT;
    a_int.V.val.IntVal = a.V.val.BoolVal;
    return single_int(a_int,op);
}

NodeAttribute single_error(NodeAttribute a, std::string op) {
    //error_msgs.push_back("operator is invalid in line " + std::to_string(a.line_number) + "\n");
    NodeAttribute result;
    result.T.type = Type::VOID;
    result.V.ConstTag = 0;
    return result;
}


NodeAttribute cal_single_attribute(NodeAttribute a,std::string op){
    if(a.T.type==Type::INT){
        return single_int(a,op);
    }
    else if(a.T.type==Type::FLOAT){
        return single_float(a,op);
    }
    else if(a.T.type==Type::BOOL){
        return single_bool(a,op);
    }
    else if(a.T.type==Type::PTR){
        return single_error(a,op);
    }
    else if(a.T.type==Type::VOID){
        return single_error(a,op);
    }
}



void __Program::TypeCheck() {
    semant_table.symbol_table.enter_scope();
    auto comp_vector = *comp_list;
    for (auto comp : comp_vector) {
        comp->TypeCheck();
    }
    if (!mainFound) {
        error_msgs.push_back("main function does not defined.\n");
    }
    semant_table.symbol_table.exit_scope();
}

void Exp::TypeCheck() {
    addexp->TypeCheck();

    attribute = addexp->attribute;
}

void AddExp_plus::TypeCheck() {
    addexp->TypeCheck();
    mulexp->TypeCheck();

    ////TODO("BinaryExp Semant");
    //我大概知道了，这里就要分类讨论，得到最后的属性值attribute，如果中间有错误的话就放error_msgs里面
    attribute=cal_binary_attribute(addexp->attribute,mulexp->attribute,"+");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void AddExp_sub::TypeCheck() {
    addexp->TypeCheck();
    mulexp->TypeCheck();

    ////TODO("BinaryExp Semant");
    attribute=cal_binary_attribute(addexp->attribute,mulexp->attribute,"-");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void MulExp_mul::TypeCheck() {
    mulexp->TypeCheck();
    unary_exp->TypeCheck();

    ////TODO("BinaryExp Semant");
    attribute=cal_binary_attribute(mulexp->attribute,unary_exp->attribute,"*");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void MulExp_div::TypeCheck() {
    mulexp->TypeCheck();
    unary_exp->TypeCheck();

    // 检查除数是否为零
    if (unary_exp->attribute.V.val.IntVal == 0 && unary_exp->attribute.V.ConstTag && unary_exp->attribute.T.type == Type::INT) {
        // 抛出错误或记录错误信息
        error_msgs.push_back("Division by zero in line " + std::to_string(unary_exp->GetLineNumber()) + "\n");
        attribute.T.type = Type::VOID;
        attribute.V.ConstTag = false;
        return;
    }

    ////TODO("BinaryExp Semant");
    attribute=cal_binary_attribute(mulexp->attribute,unary_exp->attribute,"/");

    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}



void MulExp_mod::TypeCheck() {
    mulexp->TypeCheck();
    unary_exp->TypeCheck();

    // 检查操作数是否为float
    if (mulexp->attribute.T.type == Type::FLOAT||unary_exp->attribute.T.type == Type::FLOAT) {
        // 抛出错误或记录错误信息
        error_msgs.push_back("mod by float in line " + std::to_string(unary_exp->GetLineNumber()) + "\n");
        attribute.T.type = Type::VOID;
        attribute.V.ConstTag = false;
        return;
    }

    ////TODO("BinaryExp Semant");
    attribute=cal_binary_attribute(mulexp->attribute,unary_exp->attribute,"%");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void RelExp_leq::TypeCheck() {
    relexp->TypeCheck();
    addexp->TypeCheck();

    ////TODO("BinaryExp Semant");
    attribute=cal_binary_attribute(relexp->attribute,addexp->attribute,"<=");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void RelExp_lt::TypeCheck() {
    relexp->TypeCheck();
    addexp->TypeCheck();

    ////TODO("BinaryExp Semant");
    attribute=cal_binary_attribute(relexp->attribute,addexp->attribute,"<");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void RelExp_geq::TypeCheck() {
    relexp->TypeCheck();
    addexp->TypeCheck();

    ////TODO("BinaryExp Semant");
    attribute=cal_binary_attribute(relexp->attribute,addexp->attribute,">=");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void RelExp_gt::TypeCheck() {
    relexp->TypeCheck();
    addexp->TypeCheck();

    ////TODO("BinaryExp Semant");
    attribute=cal_binary_attribute(relexp->attribute,addexp->attribute,">");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void EqExp_eq::TypeCheck() {
    eqexp->TypeCheck();
    relexp->TypeCheck();

    ////TODO("BinaryExp Semant");
    attribute=cal_binary_attribute(eqexp->attribute,relexp->attribute,"==");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void EqExp_neq::TypeCheck() {
    eqexp->TypeCheck();
    relexp->TypeCheck();

    ////TODO("BinaryExp Semant");
    attribute=cal_binary_attribute(eqexp->attribute,relexp->attribute,"!=");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void LAndExp_and::TypeCheck() {
    landexp->TypeCheck();
    eqexp->TypeCheck();

    ////TODO("BinaryExp Semant");
    attribute=cal_binary_attribute(landexp->attribute,eqexp->attribute,"&&");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void LOrExp_or::TypeCheck() {
    lorexp->TypeCheck();
    landexp->TypeCheck();

    ////TODO("BinaryExp Semant");
    attribute=cal_binary_attribute(lorexp->attribute,landexp->attribute,"||");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void ConstExp::TypeCheck() {
    addexp->TypeCheck();
    attribute = addexp->attribute;
    if (!attribute.V.ConstTag) {    // addexp is not const
        error_msgs.push_back("Expression is not const " + std::to_string(line_number) + "\n");
    }
}

/*void Lval::TypeCheck() { //TODO("Lval Semant"); 
    VarAttribute val=semant_table.symbol_table.lookup_val(name);
    
    if(semant_table.GlobalTable.find(name)!=semant_table.GlobalTable.end()){
        attribute.T.type=semant_table.GlobalTable[name].type;
        scope = 0;
    }else if(semant_table.symbol_table.lookup(name))
    {
        attribute.T.type=semant_table.symbol_table.lookup_type(name);
        scope = 1;
    }else {
         error_msgs.push_back("var not def " + std::to_string(line_number) +
                                     "\n");
    }
    //左值类型不能为void
    if(attribute.T.type==Type::VOID){
        error_msgs.push_back("Lval can't be void type " + std::to_string(line_number) +
                                     "\n");
    }
    // 如果dims为nullptr, 表示该变量不含数组下标, 如果你在语法分析中采用了其他方式处理，这里也需要更改
    if (dims != nullptr) {    
        auto dim_vector = *dims;
        std::vector<int> under;
        int count=0;
        //val.dims.push_back(-1);    // 这里用-1表示empty，你也可以使用其他方式
        for (int i = 0; i < dim_vector.size(); ++i) {
            auto d = dim_vector[i];
            
            
            d->TypeCheck();
            if (d->attribute.V.ConstTag == false) {
                error_msgs.push_back("Array Dim must be const expression in line " + std::to_string(line_number) +
                                     "\n");
            }
            if (d->attribute.T.type == Type::FLOAT) {
                error_msgs.push_back("Array Dim can not be float in line " + std::to_string(line_number) + "\n");
            }
            under.push_back(d->attribute.V.val.IntVal);
            //val.dims.push_back(d->attribute.V.val.IntVal);
        }
        int current=1;
        for(int i=0;i<under.size();i++){
            
            for(int j=val.dims.size()-1;j>i;j--){
                current*=val.dims[j];
            }count+=current*under[i];
            current=1;
        }
        if(dims->size()==semant_table.symbol_table.lookup_val(name).dims.size()){
            attribute.V.ConstTag=semant_table.symbol_table.lookup_val(name).ConstTag;
            if(attribute.T.type==Type::INT){
                attribute.V.val.IntVal=semant_table.symbol_table.lookup_val(name).IntInitVals[count];
            }
            else if(attribute.T.type==Type::FLOAT){
                attribute.V.val.FloatVal=semant_table.symbol_table.lookup_val(name).FloatInitVals[count];
            }
        }
        else if(dims->size()<semant_table.symbol_table.lookup_val(name).dims.size()){
                 attribute.T.type=Type::PTR;
        }else if(dims->size()>semant_table.symbol_table.lookup_val(name).dims.size()){
                error_msgs.push_back("Array Dim beyond define " + std::to_string(line_number) + "\n");
        }
       // attribute.T.type = Type::PTR;
    } else {
        //attribute.T.type = type_decl;
    }
}*/
//reference虽然是reference,但是没用上
/*int GetArrayVal(VarAttribute &val, std::vector<int> &indexs,Type::ty type) {
    //[i] + i
    //[i][j] + i*dim[1] + j
    //[i][j][k] + i*dim[1]*dim[2] + j*dim[2] + k
    //[i][j][k][w] + i*dim[1]*dim[2]*dim[3] + j*dim[2]*dim[3] + k*dim[3] + w
    int idx = 0;
    for (int curIndex = 0; curIndex < indexs.size(); curIndex++) {
        idx *= val.dims[curIndex];
        idx += indexs[curIndex];
    }
    if(type==Type::INT){
        return val.IntInitVals[idx];
    }else if(type==Type::FLOAT){
        return val.FloatInitVals[idx];
    }
}*/
void Lval::TypeCheck() { //TODO("Lval Semant"); 
    VarAttribute val;
    std::vector<int> under{};
    bool arrayindexConstTag = true;
    int count=0; 
    /*if(semant_table.GlobalTable.find(name)!=semant_table.GlobalTable.end()){
        val=semant_table.GlobalTable[name];
        attribute.T.type=semant_table.GlobalTable[name].type;
        scope = 0;
    }else */if(semant_table.symbol_table.lookup(name))
    {   
        val=semant_table.symbol_table.lookup_val(name);
        attribute.T.type=semant_table.symbol_table.lookup_type(name);
        scope = semant_table.symbol_table.get_current_scope();
    }else {
         error_msgs.push_back("var not def " + std::to_string(line_number) +
                                     "\n");
    }
    //左值类型不能为void
    if(attribute.T.type==Type::VOID){
        error_msgs.push_back("Lval can't be void type " + std::to_string(line_number) +
                                     "\n");
    }
    // 如果dims为nullptr, 表示该变量不含数组下标, 如果你在语法分析中采用了其他方式处理，这里也需要更改
    if (dims != nullptr) {    
        auto dim_vector = *dims;   
        //std::cerr<<dims->size()<<std::endl;       
        for (int i = 0; i < dim_vector.size(); ++i) {
            auto d = dim_vector[i];           
            d->TypeCheck();
            /*if (d->attribute.V.ConstTag == false) {
                error_msgs.push_back("Array Dim must be const expression in line " + std::to_string(line_number) +
                                     "\n");
            }*/
            if (d->attribute.T.type == Type::FLOAT) {
                error_msgs.push_back("Array Dim can not be float in line " + std::to_string(line_number) + "\n");
            }
            if (d->attribute.T.type == Type::VOID) {
                error_msgs.push_back("Array Dim can not be void in line " + std::to_string(line_number) + "\n");
            }
            under.push_back(d->attribute.V.val.IntVal);
            arrayindexConstTag &= d->attribute.V.ConstTag;
        }
        int current=1;
        for(int i=0;i<under.size();i++){
            
            for(int j=val.dims.size()-1;j>i;j--){
                current*=val.dims[j];
            }count+=current*under[i];
            current=1;
        }
    }
    if(under.size()==val.dims.size()){
        attribute.V.ConstTag = val.ConstTag & arrayindexConstTag;
        if (attribute.V.ConstTag) {          
             if (attribute.T.type == Type::INT) {
                //attribute.V.val.IntVal = GetArrayVal(val, under,Type::INT);
                attribute.V.val.IntVal=val.IntInitVals[count];
            } else if (attribute.T.type == Type::FLOAT) {
                //attribute.V.val.FloatVal = GetArrayVal(val, under,Type::FLOAT);
                attribute.V.val.FloatVal=val.FloatInitVals[count];
            }
        }
    }
    else if(under.size()<val.dims.size()){
        attribute.V.ConstTag = false;
        attribute.T.type=Type::PTR;
    }else if(under.size()>val.dims.size()){
        std::cerr<<"under.size()"<<under.size()<<std::endl;
        std::cerr<<"val.dims.size()"<<val.dims.size()<<std::endl;
        error_msgs.push_back("Array Dim beyond define " + std::to_string(line_number) + "\n");
    }
}
void FuncRParams::TypeCheck() {
    auto exp_vector = *params;
    for (auto exp : exp_vector) {
        exp->TypeCheck();
    }
     //TODO("FuncRParams Semant"); 
     }
     // 添加一个辅助函数来判断类型转换是否合法
    
bool canImplicitlyConvert(Type::ty from, Type::ty to) {
    if (from == to) return true;
    
    // bool 可以转换为 int 或 float
    if (from== Type::PTR || to== Type::PTR) {
        return false;
    }
    if (from== Type::VOID || to== Type::VOID) {
        return false;
    }
    return true;
}
void Func_call::TypeCheck() { 
    //实参检查
    if(funcr_params!=nullptr)
    funcr_params->TypeCheck();
    int formal_size=0; 
    int params_size=0;
    if (semant_table.FunctionTable.find(name) != semant_table.FunctionTable.end()) {//就是说有这个函数的意思
    
            auto func_def = semant_table.FunctionTable[name];
        
        // 添加一个标记来判断是否已经进行过类型检查
        static std::set<std::string> checked_functions;
        if (checked_functions.find(name->get_string()) == checked_functions.end()) {
            checked_functions.insert(name->get_string());
            func_def->TypeCheck();
        }
        
        if(func_def->formals != nullptr) {
            formal_size = func_def->formals->size(); 
        }
            if(getParams()!=nullptr){
                params_size=getParams()->size(); 
            }
             if (formal_size!= params_size) {
                error_msgs.push_back( "Error: Number of formals and actuals do not match"+ std::to_string(line_number) + "\n");
            }
            //这儿需要比较实参和形参，但是我不知道怎么搞到exp的type
            
            else{ 
                auto params = ((FuncRParams *)funcr_params)->params;
                for (size_t i = 0; i < params_size; ++i) {
                    const FuncFParam& formal = (*semant_table.FunctionTable[name]->formals)[i];
                    
                    const Expression& actual = (*getParams())[i];  // 解引用指针
                    //std::cerr<<"获得的形参类型"<<formal->attribute.T.type<<std::endl;
                    //std::cerr<<"实参类型"<<actual->attribute.T.type<<std::endl;
                    // 进行某种比较，例如类型检查
                    if (!canImplicitlyConvert(formal->attribute.T.type,actual->attribute.T.type)) {
                        error_msgs.push_back( "Error: Type of formals and actuals do not match in line"+ std::to_string(line_number) + "\n");
                        
                    }
                }
                //attribute=semant_table.FunctionTable[name];
                attribute.T.type = semant_table.FunctionTable[name]->return_type;
            }
    }       
    else{
        error_msgs.push_back("function have not def: " + name->get_string() + " in line " +
                                 std::to_string(line_number) + "\n");
    }
   
    //TODO("FunctionCall Semant"); 
    }

//这里是单目运算
void UnaryExp_plus::TypeCheck() { 
    ////TODO("UnaryExp Semant"); 
    unary_exp->TypeCheck();
    attribute=cal_single_attribute(unary_exp->attribute,"+");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void UnaryExp_neg::TypeCheck() { 
    ////TODO("UnaryExp Semant"); 
    unary_exp->TypeCheck();
    attribute=cal_single_attribute(unary_exp->attribute,"-");
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void UnaryExp_not::TypeCheck() { 
    ////TODO("UnaryExp Semant");
    unary_exp->TypeCheck();
    attribute=cal_single_attribute(unary_exp->attribute,"!"); 
    if (attribute.T.type == Type::VOID)
    {
        error_msgs.push_back("invalid operators in line " + std::to_string(line_number) + "\n");
    }
}

void IntConst::TypeCheck() {
    attribute.T.type = Type::INT;
    attribute.V.ConstTag = true;
    attribute.V.val.IntVal = val;
}

void FloatConst::TypeCheck() {
    attribute.T.type = Type::FLOAT;
    attribute.V.ConstTag = true;
    attribute.V.val.FloatVal = val;
}

void StringConst::TypeCheck() { //TODO("StringConst Semant");
 }//没做，不写了

void PrimaryExp_branch::TypeCheck() {
    exp->TypeCheck();
    attribute = exp->attribute;
}

void assign_stmt::TypeCheck() { 
    lval->TypeCheck();
    exp->TypeCheck();
    attribute = lval->attribute;
    if(exp->attribute.T.type==Type::VOID){
        error_msgs.push_back("assign_stmt expression can not be void type"+std::to_string(line_number)+"\n");
    }
    //TODO("AssignStmt Semant");
}

void expr_stmt::TypeCheck() {
    exp->TypeCheck();
    attribute = exp->attribute;
}

void block_stmt::TypeCheck() { b->TypeCheck(); }

void ifelse_stmt::TypeCheck() {
    Cond->TypeCheck();
    if (Cond->attribute.T.type == Type::VOID) {
        error_msgs.push_back("if cond type is invalid " + std::to_string(line_number) + "\n");
    }
    ifstmt->TypeCheck();
    elsestmt->TypeCheck();
}

void if_stmt::TypeCheck() {
    Cond->TypeCheck();
    if (Cond->attribute.T.type == Type::VOID) {
        error_msgs.push_back("if cond type is invalid " + std::to_string(line_number) + "\n");
    }
    ifstmt->TypeCheck();
}

void while_stmt::TypeCheck() {
    Cond->TypeCheck();
    if (Cond->attribute.T.type == Type::VOID) {
        error_msgs.push_back("while cond type is invalid " + std::to_string(line_number) + "\n");
    }
    body->TypeCheck();
     //TODO("WhileStmt Semant"); 
    }
//continue,break需要判断是否在循环体内，不知道怎么实现，但是实验要求里没有，先不做
void continue_stmt::TypeCheck() { 
    //TODO("ContinueStmt Semant"); 
    }

void break_stmt::TypeCheck() { //TODO("BreakStmt Semant");
 }

void return_stmt::TypeCheck() { 
    return_exp->TypeCheck(); 
    if (return_exp->attribute.T.type == Type::VOID) {
        error_msgs.push_back("return type is invalid in line " + std::to_string(line_number) + "\n");
    }
}

void return_stmt_void::TypeCheck() {}
//常量初值
void ConstInitVal::TypeCheck() { 
    auto init_vector = *initval;
    
    for (auto init : init_vector) {
        init->TypeCheck();
        
    }
    //这里需要加attribute吗应该不用吧
    //TODO("ConstInitVal Semant"); 
    }

void ConstInitVal_exp::TypeCheck() { 
    exp->TypeCheck();
    attribute=exp->attribute;
    if (attribute.T.type == Type::VOID) {
        error_msgs.push_back("const Initval expression can not be void in line " + std::to_string(line_number) + "\n");
    }
    if (!attribute.V.ConstTag) {    // addexp is not const
        error_msgs.push_back("Expression is not const " + std::to_string(line_number) + "\n");
    }
    //TODO("ConstInitValExp Semant"); 
    }

void VarInitVal::TypeCheck() { 
    auto init_vector = *initval;
    
    for (auto init : init_vector) {
        init->TypeCheck();
        
    }
    //TODO("VarInitVal Semant");
     }

void VarInitVal_exp::TypeCheck() { 
    exp->TypeCheck();
    attribute=exp->attribute;
    if (attribute.T.type == Type::VOID) { 
        error_msgs.push_back("Expression is void in line" + std::to_string(line_number) + "\n");
    }
    //TODO("VarInitValExp Semant");
}
//reference
void SaveInitVals(InitVal init, VarAttribute& val) {
        if (auto const_init_val = dynamic_cast<ConstInitVal*>(init)) {
            // 递归处理数组初始化列表
            for (auto init : *(const_init_val->initval)) {
                SaveInitVals(init, val);
            }
        } else if (auto var_init_val = dynamic_cast<VarInitVal*>(init)) {
            // 递归处理数组初始化列表
            for (auto init : *(var_init_val->initval)) {
                SaveInitVals(init, val);
            }
        } else if (auto const_init_exp = dynamic_cast<ConstInitVal_exp*>(init)) {
            // 处理单个表达式初始化
            if (val.type == Type::INT) {
                //val.IntInitVals.push_back(const_init_exp->exp->attribute.V.val.IntVal);
                if (const_init_exp->attribute.T.type == Type::VOID) {
                        error_msgs.push_back("Expression can not be void in initval in line " +
                                            std::to_string(init->GetLineNumber()) + "\n");
                } else if (const_init_exp->attribute.T.type == Type::INT) {
                    val.IntInitVals.push_back(const_init_exp->exp->attribute.V.val.IntVal);
                } else if (const_init_exp->attribute.T.type == Type::FLOAT) {
                    val.IntInitVals.push_back((int)(const_init_exp->exp->attribute.V.val.FloatVal));
                }
            
            } else if (val.type == Type::FLOAT) {
                //val.FloatInitVals.push_back(const_init_exp->exp->attribute.V.val.FloatVal);
                if (const_init_exp->attribute.T.type == Type::VOID) {
                        error_msgs.push_back("Expression can not be void in initval in line " +
                                            std::to_string(init->GetLineNumber()) + "\n");
                } else if (const_init_exp->attribute.T.type == Type::INT) {
                    val.FloatInitVals.push_back((float)(const_init_exp->exp->attribute.V.val.IntVal));
                } else if (const_init_exp->attribute.T.type == Type::FLOAT) {
                    val.FloatInitVals.push_back(const_init_exp->exp->attribute.V.val.FloatVal);
                }
            }
        } else if (auto var_init_exp = dynamic_cast<VarInitVal_exp*>(init)) {
            // 处理单个表达式初始化
            if (val.type == Type::INT) {
                //val.IntInitVals.push_back(var_init_exp->exp->attribute.V.val.IntVal);
                if (var_init_exp->attribute.T.type == Type::VOID) {
                        error_msgs.push_back("Expression can not be void in initval in line " +
                                            std::to_string(init->GetLineNumber()) + "\n");
                } else if (var_init_exp->attribute.T.type == Type::INT) {
                    val.IntInitVals.push_back(var_init_exp->exp->attribute.V.val.IntVal);
                } else if (var_init_exp->attribute.T.type == Type::FLOAT) {
                    //std::cerr<<"到"<<(int)(var_init_exp->exp->attribute.V.val.FloatVal)<<std::endl;
                    val.IntInitVals.push_back((int)(var_init_exp->exp->attribute.V.val.FloatVal));
                }
            } else if (val.type == Type::FLOAT) {
                //val.FloatInitVals.push_back(var_init_exp->exp->attribute.V.val.FloatVal);
                if (var_init_exp->attribute.T.type == Type::VOID) {
                        error_msgs.push_back("Expression can not be void in initval in line " +
                                            std::to_string(init->GetLineNumber()) + "\n");
                } else if (var_init_exp->attribute.T.type == Type::INT) {
                    val.FloatInitVals.push_back((float)(var_init_exp->exp->attribute.V.val.IntVal));
                } else if (var_init_exp->attribute.T.type == Type::FLOAT) {
                    val.FloatInitVals.push_back(var_init_exp->exp->attribute.V.val.FloatVal);
                }
            }
        }
    }
void VarDef_no_init::TypeCheck() { 
    scope=semant_table.symbol_table.get_current_scope();
    VarAttribute val;
    val.ConstTag = false;
    val.type=attribute.T.type;
    // 如果dims为nullptr, 表示该变量不含数组下标, 如果你在语法分析中采用了其他方式处理，这里也需要更改
    if (dims != nullptr) {    
        auto dim_vector = *dims;
        //val.dims.push_back(-1);    // 这里用-1表示empty，你也可以使用其他方式
        for (int i = 0; i < dim_vector.size(); ++i) {
            auto d = dim_vector[i];
            d->TypeCheck();
            if (d->attribute.V.ConstTag == false) {
                error_msgs.push_back("Array Dim must be const expression in line " + std::to_string(line_number) +
                                     "\n");
            }
            if (d->attribute.T.type == Type::FLOAT) {
                error_msgs.push_back("Array Dim can not be float in line " + std::to_string(line_number) + "\n");
            }
            val.dims.push_back(d->attribute.V.val.IntVal);
        }
        
    } 

    if (name != nullptr) {
        if (semant_table.symbol_table.lookup_scope(name) == semant_table.symbol_table.get_current_scope()) {
            error_msgs.push_back("multiple definition of " + name->get_string() + " exists in line " +
                                 std::to_string(line_number) + "\n");
        }
        semant_table.symbol_table.add_Symbol(name, val);
        if(GlobalTag)
        semant_table.GlobalTable[name]=val;
    }

    //TODO("VarDefNoInit Semant"); 
    }

void VarDef::TypeCheck() {
    scope=semant_table.symbol_table.get_current_scope();
    VarAttribute val;
    val.ConstTag = false;
    val.GlobalTag=GlobalTag;
    val.type=attribute.T.type;
    init->TypeCheck();
    // 如果dims为nullptr, 表示该变量不含数组下标, 如果你在语法分析中采用了其他方式处理，这里也需要更改
    if (dims != nullptr) {    
        auto dim_vector = *dims;
        //val.dims.push_back(-1);    // 这里用-1表示empty，你也可以使用其他方式
        for (int i = 0; i < dim_vector.size(); ++i) {
            auto d = dim_vector[i];
            d->TypeCheck();
            if (d->attribute.V.ConstTag == false) {
                error_msgs.push_back("Array Dim must be const expression in line " + std::to_string(line_number) +
                                     "\n");
            }
            if (d->attribute.T.type == Type::FLOAT) {
                error_msgs.push_back("Array Dim can not be float in line " + std::to_string(line_number) + "\n");
            }
            val.dims.push_back(d->attribute.V.val.IntVal);
        }
        
        //感觉定义部分的attribute应该在声明做
    } 
    SaveInitVals(init, val);
    if (name != nullptr) {
        /* if (semant_table.symbol_table.lookup_scope(name) != -1||semant_table.GlobalTable.find(name)!=semant_table.GlobalTable.end()) {
            error_msgs.push_back("multiple difinitions of formals in function " + name->get_string() + " in line " +
                                 std::to_string(line_number) + "\n");
        } */
        if (semant_table.symbol_table.lookup_scope(name) == semant_table.symbol_table.get_current_scope()) {
            error_msgs.push_back("multiple definition of " + name->get_string() + " exists in line " +
                                 std::to_string(line_number) + "\n");
        }
        semant_table.symbol_table.add_Symbol(name, val);
        if(GlobalTag)
        {semant_table.GlobalTable[name]=val;
        StaticGlobalMap[name->get_string()] = val;}
    }

     //TODO("VarDef Semant"); 
    }

void ConstDef::TypeCheck() {
    scope=semant_table.symbol_table.get_current_scope();
    VarAttribute val;
    val.ConstTag =true;
    val.GlobalTag=GlobalTag;
    val.type=attribute.T.type;
    init->TypeCheck();
    // 如果dims为nullptr, 表示该变量不含数组下标, 如果你在语法分析中采用了其他方式处理，这里也需要更改
    if (dims != nullptr) {    
        auto dim_vector = *dims;
        //val.dims.push_back(-1);    // 这里用-1表示empty，你也可以使用其他方式
        for (int i = 0; i < dim_vector.size(); ++i) {
            auto d = dim_vector[i];
            d->TypeCheck();
            if (d->attribute.V.ConstTag == false) {
                error_msgs.push_back("Array Dim must be const expression in line " + std::to_string(line_number) +
                                     "\n");
            }
            if (d->attribute.T.type == Type::FLOAT) {
                error_msgs.push_back("Array Dim can not be float in line " + std::to_string(line_number) + "\n");
            }
            val.dims.push_back(d->attribute.V.val.IntVal);
        }
       
    } 
    SaveInitVals(init, val);
    if (name != nullptr) {
        /* if (semant_table.symbol_table.lookup_scope(name) != -1||semant_table.GlobalTable.find(name)!=semant_table.GlobalTable.end()) {
            error_msgs.push_back("multiple difinitions of formals in function " + name->get_string() + " in line " +
                                 std::to_string(line_number) + "\n");
        } */
       if (semant_table.symbol_table.lookup_scope(name) == semant_table.symbol_table.get_current_scope()) {
            error_msgs.push_back("multiple definition of " + name->get_string() + " exists in line " +
                                 std::to_string(line_number) + "\n");
        }
        semant_table.symbol_table.add_Symbol(name, val);
        if(GlobalTag){
        semant_table.GlobalTable[name]=val;
        ConstGlobalMap[name->get_string()] = val;
        }
    }
    
     //TODO("ConstDef Semant"); 
     }

void VarDecl::TypeCheck() { 
    attribute.T.type = type_decl;
    if (var_def_list != nullptr) {
        auto vector = *var_def_list;
    for (auto var_def : vector) {      
        if(GlobalTag==true) {
            var_def->GlobalTag=true;
            
        }
        var_def->attribute=attribute;
        var_def->TypeCheck();
    }
    }
    //TODO("VarDecl Semant"); 
}

void ConstDecl::TypeCheck() { 
    attribute.V.ConstTag=true;
    attribute.T.type = type_decl;
    if (var_def_list != nullptr) {
        auto vector = *var_def_list;
    for (auto var_def : vector) {     
        if(GlobalTag==true) {
            var_def->GlobalTag=true;
            
        }  
        var_def->attribute=attribute;
        var_def->TypeCheck();
    }
    }
    //TODO("ConstDecl Semant"); 
}

void BlockItem_Decl::TypeCheck() { decl->TypeCheck(); }

void BlockItem_Stmt::TypeCheck() { stmt->TypeCheck(); }

void __Block::TypeCheck() {
    semant_table.symbol_table.enter_scope();
    auto item_vector = *item_list;
    for (auto item : item_vector) {
        item->TypeCheck();
    }
    semant_table.symbol_table.exit_scope();
}
//函数形参
void __FuncFParam::TypeCheck() {
    VarAttribute val;
    val.ConstTag = false;
    val.type = type_decl;
    scope = 1;//说明进入函数里面了

    // 如果dims为nullptr, 表示该变量不含数组下标, 如果你在语法分析中采用了其他方式处理，这里也需要更改
    if (dims != nullptr) {    
        auto dim_vector = *dims;

        // the fisrt dim of FuncFParam is empty
        // eg. int f(int A[][30][40])
        val.dims.push_back(-1);    // 这里用-1表示empty，你也可以使用其他方式
        for (int i = 1; i < dim_vector.size(); ++i) {
            auto d = dim_vector[i];
            d->TypeCheck();
            if (d->attribute.V.ConstTag == false) {
                error_msgs.push_back("Array Dim must be const expression in line " + std::to_string(line_number) +
                                     "\n");
            }
            if (d->attribute.T.type == Type::FLOAT) {
                error_msgs.push_back("Array Dim can not be float in line " + std::to_string(line_number) + "\n");
            }
            val.dims.push_back(d->attribute.V.val.IntVal);
        }
        //std::cerr<<"到这"<<std::endl;
        attribute.T.type = Type::PTR;
        //val.type=Type::PTR;
    
    } else {
        attribute.T.type = type_decl;
        //val.type = type_decl;
    }
    

    if (name != nullptr) {
        if (semant_table.symbol_table.lookup_scope(name) == semant_table.symbol_table.get_current_scope()) {
            error_msgs.push_back("multiple difinitions of formals in function " + name->get_string() + " in line " +
                                 std::to_string(line_number) + "\n");
        }
        semant_table.symbol_table.add_Symbol(name, val);
    }
}

void __FuncDef::TypeCheck() {
    semant_table.symbol_table.enter_scope();
    attribute.T.type=return_type;
    if (name->get_string() == "main") {
        mainFound = true;
    }
    //函数加到函数表
    semant_table.FunctionTable[name] = this;
    //检查参数
    auto formal_vector = *formals;
    for (auto formal : formal_vector) {
        //formals形参表
        formal->TypeCheck();
        //std::cerr<<"形参类型"<<formal->attribute.T.type<<std::endl;
    }

    // 检查函数体
    if (block != nullptr) {
        auto item_vector = *(block->item_list);
        for (auto item : item_vector) {
            item->TypeCheck();
        }
    }

    semant_table.symbol_table.exit_scope();
}
void CompUnit_Decl::TypeCheck() { 
    decl->GlobalTag=true;
    decl->TypeCheck();
    
    //decl->global=true;
    //TODO("CompUnitDecl Semant"); 
}
//要在这里处理下全局变量
//void CompUnit_Decl::TypeCheck() { TODO("CompUnitDecl Semant"); }

void CompUnit_FuncDef::TypeCheck() { 
    func_def->TypeCheck(); 
    //下面是改动部分
    /*if(!semant_table.hasMainFunction()){
    error_msgs.push_back("main not found ");
    
    };*/
}//没加//TODO的可以改吗？感觉这里要改一下找main用